package com.triones.api.service.third;

import cn.hutool.core.util.IdUtil;
import com.getui.push.v2.sdk.api.PushApi;
import com.getui.push.v2.sdk.api.UserApi;
import com.getui.push.v2.sdk.common.ApiResult;
import com.getui.push.v2.sdk.dto.req.*;
import com.getui.push.v2.sdk.dto.req.message.*;
import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO;
import com.getui.push.v2.sdk.dto.req.message.android.GTNotification;
import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification;
import com.getui.push.v2.sdk.dto.req.message.android.Ups;
import com.getui.push.v2.sdk.dto.req.message.ios.Alert;
import com.getui.push.v2.sdk.dto.req.message.ios.Aps;
import com.getui.push.v2.sdk.dto.req.message.ios.IosDTO;
import com.getui.push.v2.sdk.dto.res.CidStatusDTO;
import com.ruoyi.common.utils.PushResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class GeTuiPushService {
    private final PushApi pushApi;

    private final UserApi userApi;

    /* ================= 单推（透传，仅在线） ================= */
    public PushResult pushToSingle(String cid, String title, String body) {
        PushDTO<Audience> dto = buildBaseDTO(title, body);
        dto.setAudience(buildAudience(cid));
        return doPush(pushApi.pushToSingleByCid(dto));
    }

    /* ================= 批量推（透传，仅在线） ================= */
    public PushResult pushToList(List<String> cidList, String title, String body) {
        List<PushDTO<Audience>> msgList = cidList.stream()
            .map(cid -> {
                PushDTO<Audience> dto = buildBaseDTO(title, body);
                dto.setAudience(buildAudience(cid));
                return dto;
            })
            .collect(Collectors.toList());
        PushBatchDTO batch = new PushBatchDTO();
        batch.setAsync(true);
        batch.setMsgList(msgList);
        return doPush(pushApi.pushBatchByCid(batch));
    }

    /* ================= 离线+厂商通道 ================= */
    public PushResult offlinePush(String cid, String title, String body) {
        PushDTO<Audience> dto = buildBaseDTO(title, body);

        /* -------- 厂商通道 -------- */
        PushChannel channel = new PushChannel();

        // Android
        AndroidDTO androidDTO = new AndroidDTO();
        Ups ups = new Ups();
        ThirdNotification an = new ThirdNotification();
        an.setTitle(title);
        an.setBody(body);
        an.setClickType("intent");
        an.setIntent("intent:#Intent;launchFlags=0x04000000;action=android.intent.action.oppopush;component=com.demo/.MainActivity;S.payload=test;end");
        ups.setNotification(an);
        androidDTO.setUps(ups);
        channel.setAndroid(androidDTO);

        // iOS
        IosDTO iosDTO = new IosDTO();
        Aps aps = new Aps();
        Alert alert = new Alert();
        alert.setTitle(title);
        alert.setBody(body);
        aps.setAlert(alert);
        aps.setSound("default");
        iosDTO.setAps(aps);
        channel.setIos(iosDTO);

        dto.setPushChannel(channel);

        /* -------- 离线策略 -------- */
        Settings settings = new Settings();
        Strategy strategy = new Strategy();
        strategy.setDef(1);           // 在线走个推，离线走厂商
        settings.setStrategy(strategy);
        settings.setTtl(3600 * 1000); // 离线有效期 1 小时
        dto.setSettings(settings);

        dto.setAudience(buildAudience(cid));
        return doPush(pushApi.pushToSingleByCid(dto));
    }

    /* ================= 私有工具方法 ================= */
    private PushDTO<Audience> buildBaseDTO(String title, String body) {
        PushDTO<Audience> dto = new PushDTO<>();
        dto.setRequestId(IdUtil.fastSimpleUUID());
        PushMessage pushMessage = new PushMessage();
        GTNotification notification = new GTNotification();
        notification.setTitle(title);
        notification.setBody(body);
        notification.setClickType("payload");
        notification.setPayload("{\"title\":\"" + title + "\",\"body\":\"" + body + "\"}");
        notification.setChannelName("DL");
        pushMessage.setNotification(notification);
        dto.setPushMessage(pushMessage);
        return dto;
    }

    private Audience buildAudience(String cid) {
        Audience audience = new Audience();
        audience.addCid(cid);
        return audience;
    }

    private PushResult doPush(ApiResult<?> result) {
        if (result == null) {
            return PushResult.failure("个推响应为空");
        }
        if (result.isSuccess()) {
            return PushResult.success();
        } else {
            log.error("个推失败 -> msg: {}", result.getMsg());
            return PushResult.failure(result.getMsg());
        }
    }

    /**
     * 查询用户推送状态
     *
     * @param cid 用户客户端ID
     * @return PushResult 包含用户状态的推送结果
     */
    public PushResult queryUserStatus(String cid) {
        try {
            Set<String> cidSet = Collections.singleton(cid);
            // 使用原始ApiResult类型避免泛型转换问题
            ApiResult result = userApi.queryUserStatus(cidSet);
            if (result.isSuccess() && result.getData() != null) {
                Object dataObj = result.getData();
                log.info("查询用户状态结果 -> {}", dataObj);
                // 处理返回的数据结构
                String status = "offline";
                if (dataObj instanceof Map) {
                    Map dataMap = (Map) dataObj;
                    Object statusObj = dataMap.get(cid);
                    // 直接处理StatisticDTO对象
                    if (statusObj != null) {
                        status = extractStatusFromObject(statusObj);
                    }
                }
                return PushResult.success(status);
            } else {
                log.error("查询用户状态失败 -> code: {}, message: {}", result.getCode(), result.getMsg());
                return PushResult.failure(result.getMsg());
            }
        } catch (Exception e) {
            log.error("查询用户状态异常 -> cid: {}", cid, e);
            return PushResult.failure("查询用户状态异常: " + e.getMessage());
        }
    }

    /**
     * 从对象中提取状态值
     * @param obj 状态对象
     * @return 状态字符串
     */
    private String extractStatusFromObject(Object obj) {
        try {
            // 方法1: 直接调用getStatus方法
            java.lang.reflect.Method getStatusMethod = obj.getClass().getMethod("getStatus");
            Object statusValue = getStatusMethod.invoke(obj);
            if (statusValue != null) {
                return statusValue.toString();
            }
        } catch (Exception ex1) {
            log.warn("通过getStatus方法获取状态失败: {}", ex1.getMessage());
            try {
                // 方法2: 查找所有get方法，找到可能的status字段
                java.lang.reflect.Method[] methods = obj.getClass().getMethods();
                for (java.lang.reflect.Method method : methods) {
                    if (method.getName().startsWith("get") && method.getParameterCount() == 0) {
                        String fieldName = method.getName().substring(3).toLowerCase();
                        if (fieldName.contains("status")) {
                            Object value = method.invoke(obj);
                            if (value != null) {
                                return value.toString();
                            }
                        }
                    }
                }
            } catch (Exception ex2) {
                log.warn("通过遍历get方法获取状态失败: {}", ex2.getMessage());
            }
            // 方法3: 尝试toString并解析
            try {
                String objStr = obj.toString();
                // 解析类似 StatisticDTO{status=online} 的字符串
                if (objStr.contains("status=")) {
                    int startIndex = objStr.indexOf("status=") + 7;
                    int endIndex = objStr.indexOf("}", startIndex);
                    if (endIndex == -1) {
                        endIndex = objStr.length();
                    }
                    return objStr.substring(startIndex, endIndex).trim();
                }
            } catch (Exception ex3) {
                log.warn("通过toString解析状态失败: {}", ex3.getMessage());
            }
        }
        return "offline";
    }
}
